import json

from django.http import JsonResponse
from django.shortcuts import render

# Create your views here.
# restful
# 一个路由   url  对应一个功能, 操作,  绝大多数的操作都是针对数据库的增删改查
# 前后端分离,  都是ajax请求  axios,  所有的接口都是接收json, 返回json

# api 接口 提供给 程序访问,  权限, 限流,
from django.views import View
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter
from rest_framework.generics import GenericAPIView
from rest_framework.permissions import AllowAny, IsAuthenticated, BasePermission
from rest_framework.response import Response
from rest_framework.throttling import AnonRateThrottle
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet

from demo_app.models import BookInfo, HeroInfo

# 查找书籍信息
# @装饰器判断权限
# @装饰器限流
from demo_app.sers import BookSerializer, HeroSerializer, HeroWriteSerializer, BookWriteSerializer


def book_view(request):
    if request.method == 'GET':
        books = BookInfo.objects.filter(is_delete=False)
        book_list = []

        for book in books:
            # 组装数据
            book_data = {
                'id': book.id,
                'btitle': book.btitle,
                'bpub_date': book.bpub_date,
                'bread': book.bread,
                'bcomment': book.bcomment
            }
            book_list.append(book_data)

        # JsonResponse   可以接收字典, 也可以接收列表,  如果是列表, 需要设置safe=False
        return JsonResponse(book_list, safe=False)
    if request.method == 'POST':
        # 创建书籍
        # 1. 需要从请求里获取数据
        btitle = request.POST.get('btitle')
        bpub_date = request.POST.get('bpub_date')
        # bread = request.POST.get('bread')
        # bcomment = request.POST.get('bcomment')
        # 1.1  校验数据
        if all([btitle, bpub_date]):
            pass
        else:
            return JsonResponse({'code': 999, 'msg': '缺少参数'})
        # 2. 根据数据, 创建模型对象
        book = BookInfo(btitle=btitle, bpub_date=bpub_date)
        # 3. 保存
        book.save()
        # 4. 返回结果

        return JsonResponse({
            'id': book.id,
            'btitle': book.btitle,
            'bpub_date': book.bpub_date,
            'bread': book.bread,
            'bcomment': book.bcomment
        })


class BookView(View):
    def get(self, request):
        books = BookInfo.objects.filter(is_delete=False)
        book_list = []

        for book in books:
            # 组装数据
            book_data = {
                'id': book.id,
                'btitle': book.btitle,
                'bpub_date': book.bpub_date,
                'bread': book.bread,
                'bcomment': book.bcomment
            }
            book_list.append(book_data)

        # JsonResponse   可以接收字典, 也可以接收列表,  如果是列表, 需要设置safe=False
        return JsonResponse(book_list, safe=False)

    def post(self, request):
        # 创建书籍
        # 1. 需要从请求里获取数据
        # 从POST中获取表单数据
        # 从body中获取json
        # btitle = request.POST.get('btitle')
        # bpub_date = request.POST.get('bpub_date')
        # bread = request.POST.get('bread')
        # bcomment = request.POST.get('bcomment')
        data = json.loads(request.body.decode())  # body是二进制, decode成string, json=> dict
        btitle = data.get('btitle')
        bpub_date = data.get('bpub_date')

        # 1.1  校验数据
        if all([btitle, bpub_date]):
            pass
        else:
            return JsonResponse({'code': 999, 'msg': '缺少参数'})
        # 2. 根据数据, 创建模型对象
        book = BookInfo(btitle=btitle, bpub_date=bpub_date)
        # 3. 保存
        book.save()
        # 4. 返回结果

        return JsonResponse({
            'id': book.id,
            'btitle': book.btitle,
            'bpub_date': book.bpub_date,
            'bread': book.bread,
            'bcomment': book.bcomment
        })


class MyPermission(BasePermission):
    # 只允许超级用户访问

    def has_permission(self, request, view):
        # 返回 True 或者  False
        return bool(request.user and request.user.is_superuser)


# apiview  就是针对  ajax,  都是ajax请求  axios,  所有的接口都是接收json, 返回json
class BookAPIView(APIView):
    # permission_classes = (AllowAny,)  # 处理权限的类,  允许所有人访问
    permission_classes = (IsAuthenticated,)  # 处理权限的类,  允许认证用户访问
    # permission_classes = (MyPermission,)  # 处理权限的类,  用自己定义的权限类, 只允许超级用户访问
    # restful 携带token, 需要在请求头中携带 token,  用键值对的方式
    throttle_classes = [AnonRateThrottle]  # 处理接口的限流,

    def get(self, request):
        books = BookInfo.objects.filter(is_delete=False)
        # book_list = []

        # for book in books:
        #     # 组装数据
        #     book_data = {
        #         'id': book.id,
        #         'btitle': book.btitle,
        #         'bpub_date': book.bpub_date,
        #         'bread': book.bread,
        #         'bcomment': book.bcomment
        #     }
        #     book_list.append(book_data)

        ser = BookSerializer(books, many=True)
        # ser.data  =>  book_list
        # JsonResponse   可以接收字典, 也可以接收列表,  如果是列表, 需要设置safe=False
        # return JsonResponse(book_list, safe=False)
        return Response(ser.data)  # 返回json数据

    def post(self, request):
        # 创建书籍
        # 1. 需要从请求里获取数据
        # 从POST中获取表单数据
        # 从body中获取json
        # btitle = request.POST.get('btitle')
        # bpub_date = request.POST.get('bpub_date')
        # bread = request.POST.get('bread')
        # bcomment = request.POST.get('bcomment')

        # data = json.loads(request.body.decode())  # body是二进制, decode成string, json=> dict
        # btitle = data.get('btitle')
        # bpub_date = data.get('bpub_date')

        # btitle = request.data.get('btitle')
        # bpub_date = request.data.get('bpub_date')
        #
        # # 1.1  校验数据
        # if all([btitle, bpub_date]):
        #     pass
        # else:
        #     return JsonResponse({'code': 999, 'msg': '缺少参数'})
        # # 2. 根据数据, 创建模型对象
        # book = BookInfo(btitle=btitle, bpub_date=bpub_date)
        # # 3. 保存
        # book.save()
        # # 4. 返回结果
        ser = BookWriteSerializer(data=request.data)  # 序列化器, 校验了 request.data中的内容, 保存成了模型
        if ser.is_valid():
            ser.save()
            # ser.data
            # 序列化器中, 同时会有   原始数据,  转换后的模型,  模型序列化后的json
            # ser2 = BookSerializer(instance=ser.instance)
            return Response(ser.data)
        else:
            return Response(ser.errors)


class HeroAPIView(APIView):
    def get(self, request):
        heros = HeroInfo.objects.all()
        ser = HeroSerializer(heros, many=True)
        return Response(ser.data)

    def post(self, request):
        ser = HeroWriteSerializer(data=request.data)  # 序列化器, 校验了 request.data中的内容, 保存成了模型
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)


class ModelGetMixin():
    # def get(self, requset):
    #     query = self.get_queryset()
    #     ser_class = self.get_serializer_class()  # BookSerializer
    #     ser = ser_class(query, many=True)
    #     return Response(ser.data)

    def list(self, requset):
        query = self.get_queryset()
        ser_class = self.get_serializer_class()  # BookSerializer
        ser = ser_class(query, many=True)
        return Response(ser.data)

    def get_one(self, request, pk):
        pass


class ModelPostMixin():
    def post(self, requset):
        ser_class = self.get_serializer_class()  # BookWriteSerializer
        ser = ser_class(data=requset.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)


class ModelPutMixin():
    def put(self, requset, pk):
        # 修改数据, 针对一个对象, 已存在于数据库中
        query = self.get_queryset()
        object = query.filter(id=pk).first()
        # obj = self.get_object()  #  根据url中提供的pk, 获取数据库中的一个对象

        ser_class = self.get_serializer_class()  # BookSerializer
        # BookWriteSerializer(partial)
        # ser = ser_class(instance=object, data=requset.data, partial=True)
        ser = ser_class(instance=object, data=requset.data)
        # 使用序列化器 把对象装载,  然后用 requset.data  覆盖到序列化器中,  =>  更改了 序列化器中对象的数据
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)


class ModelDeleteMixin():
    def delete(self, requset, pk):
        # 删除数据, 针对一个对象
        query = self.get_queryset()
        object = query.filter(id=pk).first()
        object.delete()
        return Response({'code': 0, 'msg': 'success'}, status=204)


class BookGenericAPIView(ModelGetMixin, ModelPostMixin, ModelPutMixin, ModelDeleteMixin, GenericAPIView):
    queryset = BookInfo.objects.filter(is_delete=False)
    serializer_class = BookSerializer

    def get_serializer_class(self):
        print(self)

        # 请求方法是什么
        # 是get  =>  BookSerializer
        if self.request.method == 'GET':
            return BookSerializer
        # 是post  =>  BookWriteSerializer
        # if self.request.method == 'POST':
        #     return BookWriteSerializer
        return BookWriteSerializer


class HeroGenericAPIView(ModelGetMixin, ModelDeleteMixin, GenericAPIView):
    queryset = HeroInfo.objects.all()
    serializer_class = HeroSerializer  # HeroWriteSerializer

    def get_serializer_class(self):
        # 请求方法是什么
        # 是get  =>  BookSerializer
        if self.request.method == 'GET':
            return HeroSerializer
        # 是post  =>  BookWriteSerializer
        # if self.request.method == 'POST':
        #     return BookWriteSerializer
        return HeroWriteSerializer


from rest_framework.pagination import PageNumberPagination


class StandardResultPagination(PageNumberPagination):
    # 指定分页的默认页容量
    page_size = 5


class BookModelViewSet(ModelViewSet):
    permission_classes = (IsAuthenticated,)  # 处理权限的类,  允许认证用户访问

    queryset = BookInfo.objects.filter(is_delete=False)
    # 指定过滤字段,不设置, 过滤功能不起效
    filter_fields = ('bread', 'btitle')
    # /books/?bread=100&btitle=传

    # 指定排序字段,不设置, 排序功能不起效
    ordering_fields = ('id', 'bread', 'bpub_date')
    # /books/?ordering=bread

    pagination_class = StandardResultPagination

    def get_serializer_class(self):
        print(self)

        # 请求方法是什么
        # 是get  =>  BookSerializer
        if self.request.method == 'GET':
            return BookSerializer
        # 是post  =>  BookWriteSerializer
        # if self.request.method == 'POST':
        #     return BookWriteSerializer
        return BookWriteSerializer


class HeroModelViewSet(ModelViewSet):
    queryset = HeroInfo.objects.filter(is_delete=False)

    def get_serializer_class(self):
        # print(self)

        # 请求方法是什么
        # 是get  =>  BookSerializer
        if self.request.method == 'GET':
            return HeroSerializer
        return HeroWriteSerializer